import fs from 'fs-extra';
import path from 'path';
import { glob } from 'glob';
import * as vueDocgen from 'vue-docgen-api';
import { VueComponent, ComponentProp, ComponentEvent, ComponentSlot, ComponentMethod, ComponentEventArgument, ComponentMethodParam, ComponentSlotBinding } from '../core/types';

/**
 * Vue组件解析器
 */
export class ComponentParser {
  private components: Map<string, VueComponent> = new Map();
  private lastUpdateTime: string = new Date().toISOString();
  private scanPaths: string[];
  private vueVersion: string;

  /**
   * 构造函数
   * @param scanPaths 要扫描的组件路径
   * @param vueVersion Vue版本 (2, 3, 或 auto)
   */
  constructor(scanPaths: string[], vueVersion: string = 'auto') {
    this.scanPaths = scanPaths;
    this.vueVersion = vueVersion;
    console.log(`初始化组件解析器，扫描路径: ${scanPaths.join(', ')}, Vue版本: ${vueVersion}`);
  }

  /**
   * 解析所有组件
   */
  async parseComponents(): Promise<void> {
    this.components.clear();
    
    for (const scanPath of this.scanPaths) {
      console.log(`开始扫描路径: ${scanPath}`);
      const componentFiles = await this.findComponentFiles(scanPath);
      console.log(`找到组件文件数量: ${componentFiles.length}`);
      
      for (const filePath of componentFiles) {
        try {
          // console.log(`解析组件: ${filePath}`);
          const component = await this.parseComponent(filePath);
          if (component) {
            this.components.set(component.id, component);
          }
        } catch (error) {
          console.error(`解析组件 ${filePath} 时出错:`, error);
        }
      }
    }
    
    this.lastUpdateTime = new Date().toISOString();
    console.log(`组件解析完成，共解析 ${this.components.size} 个组件`);
  }

  /**
   * 增量解析单个组件
   * @param filePath 组件文件路径
   */
  async parseComponentIncremental(filePath: string): Promise<void> {
    try {
      console.log(`增量解析组件: ${filePath}`);
      
      // 检查文件是否存在
      const exists = await fs.pathExists(filePath);
      if (!exists) {
        // 如果文件不存在，则从组件列表中移除
        const relativeFilePath = path.relative(process.cwd(), filePath);
        const componentId = this.generateComponentId(relativeFilePath);
        if (this.components.has(componentId)) {
          this.components.delete(componentId);
          console.log(`已移除组件: ${componentId}`);
        }
      } else {
        // 解析组件并更新
        const component = await this.parseComponent(filePath);
        if (component) {
          this.components.set(component.id, component);
          console.log(`已更新组件: ${component.id}`);
        }
      }
      
      this.lastUpdateTime = new Date().toISOString();
    } catch (error) {
      console.error(`增量解析组件 ${filePath} 时出错:`, error);
    }
  }

  /**
   * 查找组件文件
   * @param scanPath 扫描路径
   */
  private async findComponentFiles(scanPath: string): Promise<string[]> {
    const absolutePath = path.isAbsolute(scanPath) 
      ? scanPath 
      : path.resolve(process.cwd(), scanPath);
    
    // console.log(`查找路径: ${scanPath}`);
    // console.log(`绝对路径: ${absolutePath}`);
    
    // 检查路径是否存在
    const pathExists = await fs.pathExists(absolutePath);
    // console.log(`路径存在: ${pathExists}`);
    
    if (!pathExists) {
      console.warn(`路径不存在: ${absolutePath}`);
      return [];
    }
    
    // 将 Windows 路径转换为使用正斜杠的格式
    const normalizedPath = absolutePath.replace(/\\/g, '/');
    // 使用正斜杠构建模式
    const pattern = `${normalizedPath}/**/*.vue`;
    // console.log(`查找模式: ${pattern}`);
    
    try {
      // 使用 glob 10.x 版本的 API (返回 Promise)
      // console.log(`开始使用 glob 查找文件...`);
      const matches = await glob(pattern);
      // console.log(`glob 查找结果:`, matches);
      return matches;
    } catch (error) {
      console.error(`查找组件文件失败: ${error}`);
      return [];
    }
  }

  /**
   * 检查文件是否在扫描路径内
   * @param filePath 文件路径
   */
  isFileInScanPaths(filePath: string): boolean {
    const absoluteFilePath = path.isAbsolute(filePath)
      ? filePath
      : path.resolve(process.cwd(), filePath);
    
    for (const scanPath of this.scanPaths) {
      const absoluteScanPath = path.isAbsolute(scanPath)
        ? scanPath
        : path.resolve(process.cwd(), scanPath);
      
      if (absoluteFilePath.startsWith(absoluteScanPath)) {
        return true;
      }
    }
    
    return false;
  }

  /**
   * 解析单个组件
   * @param filePath 组件文件路径
   */
  protected async parseComponent(filePath: string): Promise<VueComponent | null> {
    try {
      // 使用vue-docgen-api解析组件
      const componentInfo = await vueDocgen.parse(filePath, {
        // 根据指定的Vue版本选择解析器
        alias: {},
        modules: [],
        jsx: true,
        validExtends: (fullFilePath: string) => true,
      });
      
      if (!componentInfo) {
        return null;
      }
      
      // 获取文件状态以获取修改时间
      const stats = await fs.stat(filePath);
      const relativeFilePath = path.relative(process.cwd(), filePath);
      
      // 获取Vue版本
      const vueVersion = await this.detectVueVersion(filePath);
      
      // 构建组件对象
      const component: VueComponent = {
        id: this.generateComponentId(relativeFilePath),
        name: componentInfo.displayName || path.basename(filePath, '.vue'),
        description: componentInfo.description || '',
        filePath: relativeFilePath,
        props: this.parseProps(componentInfo),
        events: this.parseEvents(componentInfo),
        slots: this.parseSlots(componentInfo),
        methods: this.parseMethods(componentInfo),
        createdAt: stats.birthtime.toISOString(),
        updatedAt: stats.mtime.toISOString(),
        vueVersion: vueVersion,
      };
      
      return component;
    } catch (error) {
      console.error(`解析组件 ${filePath} 失败:`, error);
      return null;
    }
  }

  /**
   * 解析组件属性
   */
  private parseProps(componentInfo: vueDocgen.ComponentDoc): ComponentProp[] {
    if (!componentInfo.props) {
      return [];
    }
    
    return componentInfo.props.map(prop => {
      return {
        name: prop.name,
        type: (prop.type && prop.type.name) || 'any',
        description: prop.description || '',
        defaultValue: prop.defaultValue ? String(prop.defaultValue.value) : undefined,
        required: !!prop.required,
        values: prop.values || [],
      };
    });
  }

  /**
   * 解析组件事件
   */
  private parseEvents(componentInfo: vueDocgen.ComponentDoc): ComponentEvent[] {
    if (!componentInfo.events) {
      return [];
    }
    
    return componentInfo.events.map(event => {
      return {
        name: event.name,
        description: event.description || '',
        arguments: event.properties ? event.properties.map(prop => ({
          name: prop.name || '',
          type: (prop.type && (prop.type as any).names && (prop.type as any).names.join(' | ')) || 'any',
          description: prop.description || '',
        } as ComponentEventArgument)) : [],
      };
    });
  }

  /**
   * 解析组件插槽
   */
  private parseSlots(componentInfo: vueDocgen.ComponentDoc): ComponentSlot[] {
    if (!componentInfo.slots) {
      return [];
    }
    
    return componentInfo.slots.map(slot => {
      return {
        name: slot.name || '',
        description: slot.description || '',
        bindings: slot.bindings ? slot.bindings.map(binding => ({
          name: binding.name || '',
          type: (binding.type && binding.type.name) || 'any',
          description: binding.description || '',
        } as ComponentSlotBinding)) : [],
      };
    });
  }

  /**
   * 解析组件方法
   */
  private parseMethods(componentInfo: vueDocgen.ComponentDoc): ComponentMethod[] {
    if (!componentInfo.methods) {
      return [];
    }
    
    return componentInfo.methods.map(method => {
      return {
        name: method.name,
        description: method.description || '',
        params: method.params ? method.params.map(param => ({
          name: param.name || '',
          type: (param.type && (param.type as any).names && (param.type as any).names.join(' | ')) || 'any',
          description: param.description || '',
        } as ComponentMethodParam)) : [],
        returns: method.returns ? {
          type: (method.returns.type && (method.returns.type as any).names && (method.returns.type as any).names.join(' | ')) || 'void',
          description: typeof method.returns.description === 'string' ? method.returns.description : '',
        } : undefined,
      };
    });
  }

  /**
   * 生成组件ID
   */
  private generateComponentId(filePath: string): string {
    // 使用文件路径作为组件ID
    return filePath.replace(/\\/g, '/');
  }

  /**
   * 检测组件使用的Vue版本
   */
  private async detectVueVersion(filePath: string): Promise<'2' | '3'> {
    // 如果指定了Vue版本，则直接返回
    if (this.vueVersion === '2' || this.vueVersion === '3') {
      return this.vueVersion;
    }
    
    try {
      // 尝试通过文件内容来判断Vue版本
      const content = await fs.readFile(filePath, 'utf-8');
      
      // 检查Vue 3特有的特性
      const hasSetupFunction = /<script.*setup.*>/.test(content) || /setup\s*\(/.test(content);
      const hasCompositionApi = /defineComponent\s*\(/.test(content) || /ref\s*\(/.test(content) || /reactive\s*\(/.test(content);
      
      if (hasSetupFunction || hasCompositionApi) {
        return '3';
      }
      
      // 默认返回Vue 2
      return '2';
    } catch (error) {
      console.error(`检测组件${filePath}的Vue版本失败:`, error);
      return '2'; // 默认返回Vue 2
    }
  }

  /**
   * 获取组件列表
   */
  getComponentList(): VueComponent[] {
    return Array.from(this.components.values());
  }

  /**
   * 根据ID获取组件
   */
  getComponentById(id: string): VueComponent | undefined {
    return this.components.get(id);
  }

  /**
   * 获取最后更新时间
   */
  getLastUpdateTime(): string {
    return this.lastUpdateTime;
  }
} 